package com.springcloud.sc.ucpv5.client.application.message.connect;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.Callable;

import com.springcloud.sc.ucpv5.client.application.message.DataMessageManager;
import com.springcloud.sc.ucpv5.client.application.message.MessageService;
import com.springcloud.sc.ucpv5.client.application.message.MessageServiceException;
import com.springcloud.sc.ucpv5.client.application.message.connect.UcpUserManOamSdk.OnClientSdkListener;
import com.springcloud.sc.ucpv5.client.common.CmdDefine;
import com.springcloud.sc.ucpv5.client.commondata.SecuResult;
import com.springcloud.sc.ucpv5.client.commondata.data.LoginRsp;
import com.springcloud.sc.ucpv5.client.module.datamanager.BaseDataManager;
import com.springcloud.sc.ucpv5.client.module.datamanager.LoginDataManager;
import com.springcloud.sc.ucpv5.client.util.ThreadUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TcpProBufConnect extends ConnectFather implements OnClientSdkListener {
	private static final Logger logger = LoggerFactory.getLogger(TcpProBufConnect.class);

	private synchronized static void loadNative(String nativeName) {
		String systemType = System.getProperty("os.name");
		String fileExt = (systemType.toLowerCase().indexOf("win") != -1) ? ".dll" : ".so";
		File path = new File(".");
		//将所有动态链接库dll/so文件都放在一个临时文件夹下，然后进行加载
		//这是应为项目为可执行jar文件的时候不能很方便的扫描里面文件
		//此目录放置在与项目同目录下的natives文件夹下
		String sysUserTempDir = path.getAbsoluteFile().getParent() + File.separator + "dll";
		System.out.println("------>>native lib临时存放目录 : " + sysUserTempDir);
		String fileName = nativeName + fileExt;
		InputStream in = null;
		BufferedInputStream reader = null;
		FileOutputStream writer = null;
		File tempFile = new File(sysUserTempDir + File.separator + fileName);
		/*if(!tempFile.getParentFile().exists())
			tempFile.getParentFile().mkdirs() ;
		if (tempFile.exists()) {
			tempFile.delete();
		}*/
		/*try {

			*//*String sourcePath = TcpProBufConnect.class.getResource("/dll/" + fileName).getPath();
			System.out.println( sourcePath+"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" );
			File source  = new File( sourcePath );
			Files.copy( source.toPath(), tempFile.toPath() );*//*

			//读取文件形成输入流
			in = TcpProBufConnect.class.getResourceAsStream("/dll/" + fileName);
			if (in == null){
				in = TcpProBufConnect.class.getResourceAsStream("dll/" + fileName);
			}

			reader = new BufferedInputStream(in);
			writer = new FileOutputStream(tempFile);
			byte[] buffer = new byte[10*1024];
			int bytesRead;
			while ((bytesRead = reader.read(buffer)) != -1 ) {
				writer.write( buffer , 0 , bytesRead);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (in != null){
					in.close();
				}
				if (writer != null){
					writer.flush();
					writer.close();
				}

			} catch (IOException e) {
				e.printStackTrace();
			}
		}*/
		System.load(tempFile.getPath());
		System.out.println("------>> 加载native文件 :" + tempFile + "成功!!");
	}

	static {
		loadNative("ucp_userman_oam_sdk");
	}

	/**
	 * 当前登录IP和port
	 */
	public TcpProBufConnect() {
		super();
		sessionId = 99;
		UcpUserManOamSdk.getInstance().set_cb(this);
	}
	/**
     * 
     * 
     */
	public int internalInit(final String strServerIP, final int iServerPort, boolean isReconnect) throws MessageServiceException {
		try {

			logger.info("TcpProBufConnect internalInit begin " + strServerIP + " " + iServerPort);

			if (true) {
				setConnnectClose();
			}

			logger.info("TcpProBufConnect internalInit  " + strServerIP + " " + iServerPort);

			// 标识连接是否返回,或返回结果
			connect_rsq = -1;

			Callable<Object> call = new Callable<Object>() {
				public Object call() throws Exception {
					UcpUserManOamSdk.getInstance().connect(LoginName, strServerIP, iServerPort, "");
					while (connect_rsq == -1) {
						try {
							Thread.sleep(500);
						} catch (Exception e) {}
					}

					return null;
				}
			};
			// 10 秒超时
			ThreadUtil.getInstance().TimeOutCall(call, 20);
			logger.info("internalInit 连接服务器是否成功:" + connect_rsq);
			return connect_rsq;
		} catch (Exception e) {
			logger.info("TcpProBufConnect internalInit 异常 " + strServerIP + " " + iServerPort, e);
			return ERROR_CODE_CONNECT_FAIL;
		}
	}

	public boolean isLocalPortRight() {
		return true;
	}

	public boolean isDatAvailable() {
		return false;
	}

	public void doDataToServer(MessageData messageData) {
		try {
			com.proto.uuos_sdk_pb.MsgHeader msgHeader = (com.proto.uuos_sdk_pb.MsgHeader) messageData.header.dataChangeCommonToProBufData();
			try {
				if (messageData.header.SessionID != getSessionId()) {
					// 非当前登录需要的登录消息, 丢弃
					return;
				}

				// value 转成prob对象
				com.google.protobuf.Message value = messageData.message.dataChangeCommonToProBufData();

				// System.out.println("发送内容长度:" + value.toByteString().size());

				com.proto.uuos_sdk_pb.MsgHeader.Builder builder = msgHeader.newBuilder(msgHeader);
				builder.setMsgContent(value.toByteString());
				msgHeader = builder.build();
				if (msgHeader.getCmdID() != 2106) {
					//logger.info("开始发送包:" + msgHeader.getCmdID());
					//System.out.println("开始发送包:" + msgHeader.getCmdID());
				}

				// 后台发送
				UcpUserManOamSdk.getInstance().send_pack(LoginName, msgHeader);
			} catch (Exception e) {
				e.printStackTrace();
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	public void doDataFromServer(Object msg) {
		try {
			com.springcloud.sc.ucpv5.client.commondata.data.MsgHeader header = new com.springcloud.sc.ucpv5.client.commondata.data.MsgHeader();
			header.dataChangeProBufDataToCommon((com.proto.uuos_sdk_pb.MsgHeader) msg);

			// wsy 20180725 如果上报消息的节点在服务器无法找到, 则丢弃
	    if (header.CmdID != CmdDefine.CMD_User_Login && header.CmdID != CmdDefine.CMD_User_Login_regcheck && header.CmdID != CmdDefine.CMD_User_Login_md5
		    && header.CmdID != CmdDefine.CMD_User_Login_md5_check 
		    // wsy 20181126 查询异节点组的用户信息, 且该节点对该用户不可见, 需要放开这些命令码
		    && header.CmdID != CmdDefine.CMD_Query_Group_User && header.CmdID != CmdDefine.CMD_User_Query_Status && header.CmdID != CmdDefine.CMD_User_Query_Info_detail
		    // wsy 20181126 查询异节点组的组信息, 且该节点对该用户不可见, 需要放开这些命令码
		    && header.CmdID != CmdDefine.CMD_Group_Query_Single 
		    && header.CmdID != CmdDefine.CMD_Group_Query_Mermber_Status
		    ) {
		if (BaseDataManager.getInstance().nodeGet(header.NodeNumber) == null) {
		    System.out.println("出现节点获取不到情况:" + header.NodeNumber);
		     return;
		}
	    }
//	    if (header.CmdID != 2106 && header.CmdID != 2111) {
		//logger.info("收到回应包:" + header.CmdID);
		//logger.info("收到回调数据处理:" + header.CmdID);
//	    }
			MessageService.getInstance().putMessage(header);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public synchronized int writeByteMsg(byte[] content) {
		return 0;
	}

	public boolean checkConnectOk() {
		return connect_rsq == 0;
	}

	public void setConnnectClose() {
		close();
	}

	public void close() {
	super.close();
		UcpUserManOamSdk.getInstance().disconnect(LoginName);
		sessionId = 99;
	connect_rsq = -1;
	}

	public byte[] readSocket(int len) {
		return null;
	}

	// 20180328 wsy
	private static String LoginName = "DC_Login";
	private int connect_rsq = -1;

	public void onNotify(com.proto.uuos_sdk_pb.MsgHeader msg) {
		if (msg.hasLinkState()) {
			// 连接服务器是否成功,回调
			connect_rsq = msg.getLinkState() ? 0 : 1;
			System.out.println("连接服务器是否成功:" + msg.getLinkState() + " " + connect_rsq);

			if (msg.getLinkState()) {
				// 发送连接通知信息
				sessionId++;
				if (sessionId == 100) {
					// 属于第一次的登录 , 登录消息由对话框触发
					//
				} else {
					// 发送登录消息, 后台重连成功, 自动下发
					startAutoLogin_v5();
				}

			}
		} else {
			try {
				// System.out.println("返回回调数据:" + msg.getCmdID());

				// 转换, 并发送内部处理
				if (msg != null) {
					msgQueueFromServer.put(msg);
				}

			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	// int sessionId = 99;

	public int getSessionId() {
		return sessionId;
	}

	public void communicationShakeHands() {
		// 重写, 无心跳信令
	}

	public static void startAutoLogin_v5() {
		// 启动连接线程
		Callable<Object> call = new Callable<Object>() {
			public Object call() throws Exception {
				try {
					LoginDataManager currentUser = LoginDataManager.getInstance();
					SecuResult result = new SecuResult();
					LoginRsp rsp = DataMessageManager.getInstance().LoginSystem(currentUser.getName(), currentUser.getPassWord(), result, false, true);
					if (rsp != null && rsp.Result == 0) {
						return null;
					}

				} catch (Exception e) {
					// TODO 自动生成 catch 块
					e.printStackTrace();
					return null;
				}

				return null;
			}
		};

		ThreadUtil.getInstance().Call(call);
	}

}
